package com.acme.cli;

import com.acme.domain.bank.Bank;
import com.acme.net.BankServer;
import com.acme.service.bank.BankCannotBeLoadedException;
import com.acme.service.bank.BankCannotBeSavedException;
import com.acme.service.bank.impl.BankLoaderFromFeedFile;
import com.acme.service.bank.impl.BankLoaderFromFile;
import com.acme.service.bank.impl.BankSaverToFile;
import com.acme.service.bank.impl.DummyBankLoader;


/**
 * The following scenarios are available:<br>
 * 1) "BankApplication -m" In-memory mode. Creates a few entities
 * programmatically, prints them.<br>
 * 2) "BankApplication -s" Forces to save bank to bank.ser file (file name can
 * not be specified for simplicity)<br>
 * 3) "BankApplication -l" Loads the bank from bank.ser file<br>
 * 4) "BankApplication -lf" Loads feed file from bank.data file, tries to add
 * data to the bank and then saves it to bank.ser file<br>
 * 5) "BankApplication -loadfeed <<file>>" Loads feed from <<file>>
 * 6) "BankApplication -loadbank <<file>>" Loads bank data from <<file>>
 * 7) "BankApplication -server" Runs bank in server mode
 */
public class BankApplication {
    private static final String PLEASE_PASS_FILENAME_ALONG_WITH_LOADFEED_ARG = "Please pass filename along with -loadfeed arg";
    private static final String PLEASE_PASS_FILENAME_ALONG_WITH_LOADBANK_ARG = "Please pass filename along with -loadbank arg";
    private static final String ALREADY_LOADED = "Bank has already been loaded via another program argument. Only one option from the list {-m, -lf, -l, -loadfeed, -loadbank} may be specified at a time.";
    private static final String SERVER_CANNOT_BE_STARTED_BECAUSE_BANK_IS_NOT_LOADED = "Server cannot be started, because bank is not loaded";
    private static final String BANK_CANNOT_BE_SAVED_BECAUSE_IT_IS_NOT_LOADED = "Bank cannot be saved, because it is not loaded";

    private static final String DEFAULT_BANK_SER_FILE_PATH = "bank.ser";
    private static final String DEFAULT_BANK_DATA_FILE_PATH = "bank.data";

    public static void main(final String[] args) throws Exception {
        Bank bank = null;
        boolean saveBank = false;
        boolean bankLoaded = false;
        boolean serverMode = false;
        for (int i = 0; i < args.length; i++) {
            String arg = args[i];

            switch (arg) {
                case "-s":
                    saveBank = true;
                    break;
                case "-server":
                    serverMode = true;
                    break;
                default:
                    if (!bankLoaded) {
                        switch (arg) {
                            case "-m":
                                bank = createInMemoryBank();
                                break;
                            case "-l":
                                bank = loadBankFromDataSource(DEFAULT_BANK_SER_FILE_PATH);
                                break;
                            case "-lf":
                                bank = loadBankFromFeed(DEFAULT_BANK_DATA_FILE_PATH);
                                break;
                            case "-loadfeed":
                                if (i + 1 < args.length) {
                                    bank = loadBankFromFeed(args[++i]);
                                } else {
                                    System.out.println(PLEASE_PASS_FILENAME_ALONG_WITH_LOADFEED_ARG);
                                    return;
                                }
                                break;
                            case "-loadbank":
                                if (i + 1 < args.length) {
                                    bank = loadBankFromDataSource(args[++i]);
                                } else {
                                    System.out.println(PLEASE_PASS_FILENAME_ALONG_WITH_LOADBANK_ARG);
                                    return;
                                }
                        }
                        bankLoaded = true;
                    } else {
                        System.out.println(ALREADY_LOADED);
                        return;
                    }
                    break;
            }
        }

        if (serverMode) {
            if (bank == null) {
                System.out.println(SERVER_CANNOT_BE_STARTED_BECAUSE_BANK_IS_NOT_LOADED);
                return;
            }
            startServer(bank);
        }

        if (bank == null) {
            System.out.println(BANK_CANNOT_BE_SAVED_BECAUSE_IT_IS_NOT_LOADED);
            return;
        }

        System.out.println(bank);

        if (saveBank) {
            saveBankToDataSource(bank);
        }
    }

    private static void startServer(Bank bank) {
        new BankServer(bank).start();
    }

    private static Bank loadBankFromDataSource(String bankDataFilePath) throws BankCannotBeLoadedException {
        return new BankLoaderFromFile(bankDataFilePath).load();
    }

    private static Bank loadBankFromFeed(String feedFilePath) throws BankCannotBeLoadedException {
        return new BankLoaderFromFeedFile(feedFilePath).load();
    }

    private static Bank createInMemoryBank() throws BankCannotBeLoadedException {
        return new DummyBankLoader().load();
    }

    private static void saveBankToDataSource(final Bank bank) throws BankCannotBeSavedException {
        new BankSaverToFile().save(bank, DEFAULT_BANK_SER_FILE_PATH);
    }
}